# -*- coding: utf-8 -*-
from turbogears import controllers, expose, flash
from model import Project,User
from turbogears import identity, redirect
from cherrypy import request, response
from sqlobject import SQLObjectNotFound

from svnadmin import svn
SVN=svn('/home/svn','svn')

import re, urllib

EMAIL=re.compile(r'''
\w+([-+.]\w+)*   #用户名称
@                #分割服
\w+([-.]\w+)*    #服务器名
\.               #点分割
\w+([-.]\w+)*    #域名
''', re.VERBOSE)

NAME=re.compile(r'''
\w    #英文或数字
{1,16}#最多16位
''',re.VERBOSE)

def isRe(RE,str):
    '''
    判断str是否符合正则表达式RE
    '''
    if str==None: return False
    s=RE.match(str)
    if s==None: return False
    if s.end()<len(str): return False
    return True

def getServer(url):
    '''
    获取服务器地址
    '''
    s=urllib.splittype(url)[1]
    s=urllib.splithost(s)[0]
    return urllib.splitport(s)[0]

# import logging
# log = logging.getLogger("tgsvn.controllers")

class Root(controllers.RootController):
    @expose(template="tgsvn.templates.welcome")
    @identity.require(identity.not_anonymous())
    def index(self):
        return dict(getServer=getServer)

    @expose(template="tgsvn.templates.job")
    @identity.require(identity.not_anonymous())
    def job(self):
        return dict(name="徐晨阳")

    @expose(template="tgsvn.templates.login")
    def login(self, forward_url=None, previous_url=None, *args, **kw):
        if not identity.current.anonymous \
            and identity.was_login_attempted() \
            and not identity.get_identity_errors():
            raise redirect(forward_url)
        forward_url=None
        previous_url= request.path
        if identity.was_login_attempted():
            msg=_("您输入的用户不存在或者登录密码错误。")
        elif identity.get_identity_errors():
            msg=_("请输入具有使用权限的用户和登录密码。")
        else:
            msg=_("请输入具有使用权限的用户和登录密码。")
            forward_url= request.headers.get("Referer", "/")
        response.status=403
        return dict(message=msg, previous_url=previous_url, logging_in=True,
                    original_parameters=request.params,
                    forward_url=forward_url)

    @expose()
    def logout(self):
        identity.current.logout()
        raise redirect("/")
    
    @expose()
    def default(self, title):
        '''
        默认页面
        '''
        if len(identity.current.user.groups)>0:
            if 'project_'==title[:8]:
                return self.editproject(title[8:])
            if 'user_'==title[:5]:
                return self.edituser(title[5:])
            #if 'deluser_'==title[:8]:
            #    return self.deluser(title[8:])
        flash("访问未知的页面")
        return self.index()

    @expose("tgsvn.templates.addproject")
    @identity.require(identity.in_group("admin"))
    def addproject(self, code=None, name='', note='', anon='none', auth='write'):
        '''
        增加项目
        '''
        b=False
        #根据正则表达式判断code是否符合要求
        if not isRe(RE=NAME, str=code):
            code=''
            b=True
        #转换成小写
        code = code.lower()
        if len(note)>200:
            flash('项目介绍长度不能大于200字节')
            b=True
        if len(name)>200:
            flash('项目名称不能大于200字节')
            b=True
        if b:
            return dict(code=code, name=name, note=note, anon=anon, auth=auth)
        try:
            project=Project.byCode(code)
            flash('项目代码 [ %s ] 重复'%code.encode('utf-8'))
            return dict(code=code, name=name, note=note, anon=anon, auth=auth)
        except SQLObjectNotFound:
            if SVN.createProject(code)>0:
                flash('项目 [ %s ] 不能创建，联系管理员'%code.encode('utf-8'))
            else:
                SVN.setProject(name=code, anon=anon, auth=auth)
                project = Project(code=code, name=name, note=note)
                project.anon=str(anon)
                project.auth=str(auth)
                flash('项目 [ %s ] 增加成功'%name.encode('utf-8'))
        raise redirect('project')
        
    @expose("tgsvn.templates.editproject")
    @identity.require(identity.in_group("admin"))
    def editproject(self,code=None):
        '''
        项目编辑
        '''
        if not isRe(RE=NAME, str=code):
            flash('项目代码格式错误')
        else:
            code=code.lower()
            try:
                project = Project.byCode(code)
                users = [ user for user in User.select(orderBy=User.q.created)]
                nusers = [ user for user in project.users]
                for u in nusers:
                    if u in users:
                        users.remove(u)
                #flash(str(project.users))
                return dict(code=project.code, name=project.name, note=project.note,
                            anon=project.anon, auth=project.auth, users=users, nusers=nusers)
            except SQLObjectNotFound:
                flash('错误的项目代码 [ %s ]'%code)
        raise redirect('project')

    @expose("tgsvn.templates.user")
    @identity.require(identity.in_group("admin"))
    #@expose("json")
    def user(self):
        '''
        用户列表
        '''
        users = [ user for user in User.select(orderBy = User.q.user_name) ]
        return dict(users = users)

    @expose("tgsvn.templates.adduser")
    @identity.require(identity.in_group("admin"))
    def adduser(self, user_name=None, display_name='', password='', email_address=''):
        '''
        用户增加
        '''
        if not isRe(RE=NAME, str=user_name):
            return dict(user_name='', display_name='', password='', email_address='')
        else:
            user_name=user_name.lower()
            try:
                user = User.by_user_name(user_name)
                flash("用户代码 [ %s ] 重复"%user_name.encode('utf-8'))
                return dict(user_name=user_name, display_name=display_name, 
                            password=password, email_address=email_address)
            except SQLObjectNotFound:
                if not isRe(RE=EMAIL, str=email_address):
                    flash('用户Email地址格式错误')
                    return dict(user_name=user_name, display_name=display_name, 
                                password=password, email_address=email_address)
                user = User(user_name=user_name, display_name=display_name, 
                            email_address=email_address, password=password)
                flash('新增用户 [ %s ] 成功'%display_name.encode('utf-8'))
                raise redirect('user')

    @expose("tgsvn.templates.editme")
    @identity.require(identity.not_anonymous())
    def editme(self):
        '''
        编辑我的信息
        '''
        return dict(display_name=identity.current.user.display_name.encode('utf-8'), 
                    email_address=identity.current.user.email_address)

    @expose()
    @identity.require(identity.not_anonymous())
    def setme(self, display_name, email_address):
        '''
        设置我的信息
        '''
        if not isRe(RE=EMAIL, str=email_address):
            flash('本人Email地址格式错误')
        else:
            identity.current.user.display_name=display_name
            identity.current.user.email_address=email_address
            flash('本人信息修改成功')
        raise redirect('editme')

    @expose()
    @identity.require(identity.not_anonymous())
    def setmepassword(self, oldpassword, password, rpassword):
        if oldpassword!=identity.current.user.password:
            flash("原密码错误")
        elif password!=rpassword:
            flash("密码重复输入错误")
        else:
            identity.current.user.set_password_raw(password)
            for p in identity.current.user.projects:
                SVN.setPassword(p.code, identity.current.user.user_name, password)
            flash("密码修改成功")
        raise redirect('editme')

    @expose("tgsvn.templates.edituser")
    @identity.require(identity.in_group("admin"))
    def edituser(self, user_name=None):
        '''
        用户编辑
        '''
        if not isRe(RE=NAME, str=user_name):
            flash('用户代码格式错误')
            return dict(user_name='', display_name='', email_address='')
        else:
            user_name=user_name.lower()
            try:
                user = User.by_user_name(user_name)
                if len(user.groups)==0 :
                    return dict(user_name=user_name, display_name=user.display_name, 
                            email_address=user.email_address)
                flash('请由管理员自行修改帐户信息')
            except SQLObjectNotFound:
                flash("用户代码错误")
        raise redirect('user')

    @expose()
    @identity.require(identity.in_group("admin"))
    def setpassword(self, user_name, password):
        '''
        修改用户密码
        '''
        if not isRe(RE=NAME, str=user_name):
            flash('用户代码格式错误')
        user_name=user_name.lower()
        try:
            user = User.by_user_name(user_name)
            user.set_password_raw(password)
            for p in user.projects:
                SVN.setPassword(p.code, user.user_name, password)
            flash("用户 [ %s ] 的密码修改成功"%user.display_name.encode('utf-8'))
        except SQLObjectNotFound:
            flash("用户代码错误")
        raise redirect('user')

    @expose()
    @identity.require(identity.in_group("admin"))
    def setuser(self, user_name, display_name, email_address):
      '''
      用户信息修改
      '''
      if not isRe(RE=NAME, str=user_name):
          flash('用户代码格式错误')
      elif not isRe(RE=EMAIL, str=email_address):
          flash('用户Email地址格式错误')
      else:
          user_name=user_name.lower()
          try:
              user=User.by_user_name(user_name)
              user.display_name=display_name
              #user.set_password_raw(password)
              user.email_address=email_address
              flash('用户信息修改成功')
          except SQLObjectNotFound:
              flash('用户信息修改失败，用户代码不存在')
      raise redirect('user')

    @expose()
    @identity.require(identity.in_group("admin"))
    def deluser(self, user_name):
      '''
      删除用户
      '''
      if not isRe(RE=NAME, str=user_name):
          flash('用户代码格式错误')
      else:
          try:
              user=User.by_user_name(user_name)
              if len(user.groups)>0:
                  flash('管理员 [ %s ] 不能删除'%user.display_name.encode('utf-8'))
              else:
                  for p in user.projects:
                      SVN.delUser(p.code, user.user_name)
                      user.removeProject(p)
                  User.deleteBy(user_name=user_name)
                  flash('删除用户 [ %s ] 成功'%user.display_name.encode('utf-8'))
          except SQLObjectNotFound:
              flash('删除用户失败，用户不存在')
      raise redirect('user')

    @expose("tgsvn.templates.project")
    @identity.require(identity.in_group("admin"))
    #@expose("json")
    def project(self):
        '''
        项目列表
        '''
        projects = [project for project in
                    Project.select(orderBy=Project.q.code).reversed()]
        return dict(projects=projects)

    @expose()
    @identity.require(identity.in_group("admin"))
    def setproject(self, code, name, note='', anon='none', auth='write'):
        '''
        项目信息修改
        '''
        if not isRe(RE=NAME, str=code):
            flash('项目代码格式错误')
            raise redirect('project')
        else:
            try:
                project = Project.byCode(code)
                SVN.setProject(name=code, anon=anon, auth=auth)
                project.name=name
                project.note=note
                project.anon=anon
                project.auth=auth
                flash('项目修改完毕')
                raise redirect('project')
            except SQLObjectNotFound:
                self.addproject(code=code, name=name, note=note, anon=anon, auth=auth)

    def _adduser(self,project,user_name):
        '''
        项目增加用户
        '''
        try:
            t=User.by_user_name(user_name)
            if t not in project.users:            
                project.addUser(t)
        except SQLObjectNotFound:
            flash('用户代码错误%s'%user_name.encode('utf-8'))
            raise redirect('project')

    @expose()
    @identity.require(identity.in_group("admin"))
    def setusers(self,code, user=None, *args, **kw):
        '''
        设置用户
        '''
        if not isRe(RE=NAME, str=code):
            flash('项目代码格式错误')
        else:
            try:
                p = Project.byCode(code)
                users = [ use for use in User.select(orderBy=User.q.user_name)]
                for u in users:
                    if u in p.users:
                        p.removeUser(u)
                if user!=None :
                    if 'list' in str(type(user)):
                        for u in user:
                            self._adduser(project=p,user_name=u)
                    else:
                        self._adduser(project=p,user_name=user)
                us={}
                for u in p.users:
                    us[u.user_name]=u.password
                if SVN.setUser(code, us)>0:
                    flash('项目 [ %s ] 设置用户错误，请联系管理员'%code.encode('utf-8'))
                flash('项目用户设置完毕')
            except SQLObjectNotFound:
                flash('项目代码错误，不能设置用户')
        raise redirect('project')
